package SERVLET;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import BO.AutorBO;
import BO.AutorLivroBO;
import BO.ComentarioBO;
import BO.ListaBO;
import BO.ObraBO;
import BO.StatusBO;
import DTO.AutorDTO;
import DTO.AutorLivroDTO;
import DTO.ComentarioDTO;
import DTO.ObraDTO;
import DTO.UsuarioDTO;
import UTIL.UploadUtil;

public abstract class GenericObraServlet extends HttpServlet {
    
    protected ObraBO obraBO = new ObraBO();
    protected AutorBO autorBO = new AutorBO();
    protected StatusBO statusBO = new StatusBO();
    protected ObraDTO obraDTO = new ObraDTO();
    protected ListaBO listaBO = new ListaBO();
    protected ComentarioDTO comentarioDTO = new ComentarioDTO();
    protected ComentarioBO comentarioBO = new ComentarioBO();
    protected AutorLivroBO autorLivroBO = new AutorLivroBO();
    protected List<AutorDTO> autores = new ArrayList<>();
    protected List<ObraDTO> livros = new ArrayList<>();		
    protected boolean incluindo;
    protected boolean alterando;

    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setHeader("Cache-control", "no-cache, must-revalidate");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Expires", "Fri, 25 Dec 1980 00:00:00 GMT");
        response.setHeader("Content-Type", "text/html; charset=UTF-16LE");
        

        if (request.getParameter("acao") != null) {
            if (request.getParameter("acao").equals("Nova Obra")) {
                novo(request, response);
            } else if (request.getParameter("acao").equals("Editar")) {
                editar(request, response);
            } else if (request.getParameter("acao").equals("Excluir")) {
                excluir(request, response);
            } else if (request.getParameter("acao").equals("ExcluirAutor")){
            	excluirAutor(request, response);
            } else if (request.getParameter("acao").equals("Visualizar")){
            	visualizar(request, response);
            } else if(request.getParameter("acao").equals("Comentar")){
            	comentar(request, response);
            } else if(request.getParameter("acao").equals("AdicionarAutor")){            	            
            	adicionarAutor(request, response);
            } else if(request.getParameter("acao").equals("Pesquisar")){            	
            	pesquisar(request, response);
            } else if (request.getParameter("acao").equals("Incluir")) {            	
                incluir(request, response);     
            } else if (request.getParameter("acao").equals("showImg")) {
            	response.setContentType("image/jpg");
            	if(request.getParameter("id") != null &&
            			obraBO.pesquisarPorCodigo(Long.parseLong(request.getParameter("id"))).getCapa() != null) {
	        		try{  
	        			OutputStream outputStream  = response.getOutputStream();
	        			outputStream.write(obraBO.pesquisarPorCodigo(Long.parseLong(request.getParameter("id"))).getCapa());
	        			outputStream.flush();
	        			outputStream.close();
	        		} catch (Exception e) { e.printStackTrace(); }
            	}
            } else {
            	removerListas(request, response);            	
            }
        }
    }
       
    protected void removerListas(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    	request.getSession().removeAttribute("autoresObra");
        request.getSession().removeAttribute("autores");
        redicionarPesquisarRemoverAtributo(request, response);
    }
    
    protected void novo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    	obraDTO = new ObraDTO();
        request.getSession().setAttribute("obraDTO", obraDTO);
        request.getSession().setAttribute("autores", autorBO.pesquisarTodos());
        request.getSession().removeAttribute("autoresObra");
        setIncluindo(true);
        setAlterando(false);
        redicionarIncluirAlterarRemoverAtributo(request, response);
    }
    
    protected void pesquisar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    	obraDTO.setTitulo(request.getParameter("pesquisa"));
    	request.getSession().setAttribute("obras", obraBO.pesquisarLivrosPorTitulo(obraDTO));            	
        redicionarPesquisar(request, response);
    }
    
    protected void editar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{    	
        request.getSession().setAttribute("obraDTO", obraDTO);
        request.getSession().setAttribute("autoresObra", autorBO.pesquisarAutoresDaObra(obraDTO));
        request.getSession().setAttribute("autores", autorBO.naoPesquisarAutoresDaObra(obraDTO));
        setAlterando(true);
        setIncluindo(false);
        redicionarIncluirAlterarRemoverAtributo(request, response);
    }       
    
    protected void excluir(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    	obraDTO.setCodigo(Long.parseLong(request.getParameter("id")));
        obraDTO = obraBO.pesquisarPorCodigo(obraDTO.getCodigo());
        if (!obraBO.remover(obraDTO)) {
            request.getSession().setAttribute("erro", "Erro ao realizar exclusão.");
            redicionarPesquisar(request, response);
        } else {                
        	redicionarPesquisarAtualizarLista(request, response);
        }
    }    
    
    protected void incluir(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    	String oldOne = obraDTO.getTitulo();
        criarObjeto(request);
        
        if (!obraBO.existe(obraDTO) || (isAlterando() && obraDTO.getTitulo().equals(oldOne))) {
            if (isIncluindo() ? obraBO.incluir(obraDTO) : isAlterando() ? obraBO.alterar(obraDTO) : false) {
            	obraDTO = obraBO.pesquisarPorTitulo(obraDTO.getTitulo());
            	if(isIncluindo()){
            		obraDTO.setObra(obraBO.pesquisarPorCodigo(1l));
            		obraBO.alterar(obraDTO);
            	}                                                                 
                for(AutorDTO a : autores){    
                	AutorLivroDTO autorLivroDTO = new AutorLivroDTO();
                    autorLivroDTO.setObra(obraDTO);                            
                	autorLivroDTO.setAutor(a);
                	autorLivroBO.incluir(autorLivroDTO);
                }
                alterando = incluindo = false;        
                request.getSession().removeAttribute("autoresObra");
                request.getSession().removeAttribute("autores");
                request.getSession().setAttribute("obras", obraBO.pesquisarTodosLivros());
                redicionarPesquisarRemoverAtributo(request, response);
            }
        } else {
            obraDTO.setTitulo(oldOne);
            request.getSession().setAttribute("erro", "Obra já existe.");
            redicionarIncluirAlterar(request, response);
        }          
    }
    
    protected void visualizar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    	obraDTO.setCodigo(Long.parseLong(request.getParameter("id")));
    	obraDTO = obraBO.pesquisarPorCodigo(obraDTO.getCodigo());
    	request.getSession().setAttribute("obraDTO", obraDTO);
    	request.getSession().setAttribute("rank", comentarioBO.pesquisarRankDaObra(obraDTO));
    	request.getSession().setAttribute("autoresObra", autorBO.pesquisarAutoresDaObra(obraDTO));
    	request.getSession().setAttribute("comentarios", comentarioBO.pesquisarComentariosDaObra(obraDTO));
    	request.getSession().setAttribute("status", statusBO.pesquisarTodos());
    	UsuarioDTO usuarioDTO = new UsuarioDTO();
    	usuarioDTO = (UsuarioDTO) request.getSession().getAttribute("usuarioLogado");
    	if(usuarioDTO != null) {
    		request.getSession().setAttribute("livroEstaNaLista", listaBO.pesquisarObraEstaListaUsuario(usuarioDTO, obraDTO));
    	}
        setAlterando(false);
        setIncluindo(false);
        redicionarVisualizar(request, response);
    }
    
    protected void comentar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    	criarComentario(request);
    	comentarioBO.incluir(comentarioDTO);
    	request.getSession().setAttribute("rank", comentarioBO.pesquisarRankDaObra(obraDTO));
    	request.getSession().setAttribute("comentarios", comentarioBO.pesquisarComentariosDaObra(obraDTO));
    	redicionarVisualizar(request, response);
    }
    
    protected void adicionarAutor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{    	
    	AutorDTO autor = new AutorDTO();
    	request.getSession().setAttribute("autorDTO", autor);
    	request.getRequestDispatcher(HomeServlet.paginas.get("autorIncluirAlterar")).forward(request, response);
    }
    
    protected void excluirAutor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    	AutorLivroDTO autorLivroDTO = new AutorLivroDTO();
    	autorLivroDTO.setObra(obraDTO);
    	autorLivroDTO.setAutor(autorBO.pesquisarPorCodigo(Long.parseLong(request.getParameter("id"))));
    	autorLivroBO.remover(autorLivroDTO);            		            	
    	request.getSession().setAttribute("obraDTO", obraDTO);
        request.getSession().setAttribute("autoresObra", autorBO.pesquisarAutoresDaObra(obraDTO));
        request.getSession().setAttribute("autores", autorBO.naoPesquisarAutoresDaObra(obraDTO));
        autores = new ArrayList<>();
        setAlterando(true);
        setIncluindo(false);
        redicionarIncluirAlterarRemoverAtributo(request, response);
    }
    
    protected void redicionarPesquisarRemoverAtributo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        request.getSession().removeAttribute("erro");
        redicionarPesquisar(request, response);
    }
       
    protected void redicionarIncluirAlterarRemoverAtributo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        removerAtributo(request);
        redicionarIncluirAlterar(request, response);
    }
    
    protected void removerAtributo(HttpServletRequest request){
        request.getSession().removeAttribute("erro");
    }
            
    protected void criarObjeto(HttpServletRequest request) {
    	obraDTO.setTitulo(request.getParameter("titulo"));
    	obraDTO.setDescricao(request.getParameter("descricao"));
    	obraDTO.setEditora(request.getParameter("editora"));
    	if(!request.getParameter("ano").isEmpty()){
    		obraDTO.setAno(Integer.parseInt(request.getParameter("ano")));
    	}
    	if(!request.getParameter("edicao").isEmpty()){
    		obraDTO.setEdicao(Integer.parseInt(request.getParameter("edicao")));
    	} 
    	obraDTO.setPaginas(Integer.parseInt(request.getParameter("paginas")));    	    		    
    	String[] vetAutores = request.getParameterValues("autores");
    	if(vetAutores != null && vetAutores.length > 0){	    	
	    	for(String s : vetAutores){
	    		if(s != "") {
	    			autores.add(autorBO.pesquisarPorCodigo(Long.parseLong(s)));
	    		}
	    	}       	
    	}
    	String[] vetLivros = request.getParameterValues("livros");    	
    	if(vetLivros != null && vetLivros.length > 0) {
    		for(String s : vetLivros){
    			if(s != "") {
    				livros.add(obraBO.pesquisarPorCodigo(Long.parseLong(s)));
    			}
    		}
    	}
    	UploadUtil upl = new UploadUtil();
        upl.doFilePost(request, request.getServletContext());
        obraDTO.setCapa(upl.getImg());
    }

    protected void criarComentario(HttpServletRequest request) {
    	comentarioDTO.setDescricao(request.getParameter("descricao"));
    	if(request.getParameter("rank") != null){
    		comentarioDTO.setRank(Integer.parseInt(request.getParameter("rank")));
    	}
    	comentarioDTO.setObra(obraDTO);
    	comentarioDTO.setUsuario((UsuarioDTO) request.getSession().getAttribute("usuarioLogado"));
    }
    
    protected abstract void redicionarPesquisar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;    	        
    	
    protected abstract void redicionarIncluirAlterar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
    	
    protected abstract void redicionarVisualizar(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
    
    protected abstract void redicionarPesquisarAtualizarLista(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        processRequest(request, response);
    }
       
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    public String getServletInfo() {
        return "Short description";
    }

    public boolean isIncluindo() {
        return incluindo;
    }

    public void setIncluindo(boolean incluindo) {
        this.incluindo = incluindo;
    }

    public boolean isAlterando() {
        return alterando;
    }

    public void setAlterando(boolean alterando) {
        this.alterando = alterando;
    }
}